home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP06.ZIP / CHAP06 / POLYLINE / IPERSTOR.CPP < prev    next >
C/C++ Source or Header  |  1993-04-14  |  9KB  |  336 lines

  1. /*
  2.  * IPERSTOR.CPP
  3.  * Polyline Component Object Chapter 6
  4.  *
  5.  * Implementation of the IPersistStorage interface that we expose on the
  6.  * Polyline object.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "polyline.h"
  19.  
  20.  
  21. /*
  22.  * CImpIPersistStorage:CImpIPersistStorage
  23.  * CImpIPersistStorage::~CImpIPersistStorage
  24.  *
  25.  * Constructor Parameters:
  26.  *  pObj            LPVOID pointing to the object we live in.
  27.  *  punkOuter       LPUNKNOWN of the controlling unknown.
  28.  */
  29.  
  30. CImpIPersistStorage::CImpIPersistStorage(LPVOID pObj, LPUNKNOWN punkOuter)
  31.     {
  32.     m_cRef=0;
  33.     m_pObj=pObj;
  34.     m_punkOuter=punkOuter;
  35.     return;
  36.     }
  37.  
  38.  
  39. CImpIPersistStorage::~CImpIPersistStorage(void)
  40.     {
  41.     return;
  42.     }
  43.  
  44.  
  45.  
  46.  
  47. /*
  48.  * CImpIPersistStorage::QueryInterface
  49.  * CImpIPersistStorage::AddRef
  50.  * CImpIPersistStorage::Release
  51.  *
  52.  * Purpose:
  53.  *  Standard set of IUnknown members for this interface
  54.  */
  55.  
  56. STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  57.     {
  58.     return m_punkOuter->QueryInterface(riid, ppv);
  59.     }
  60.  
  61. STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
  62.     {
  63.     ++m_cRef;
  64.     return m_punkOuter->AddRef();
  65.     }
  66.  
  67. STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
  68.     {
  69.     --m_cRef;
  70.     return m_punkOuter->Release();
  71.     }
  72.  
  73.  
  74.  
  75.  
  76.  
  77. /*
  78.  * CImpIPersistStorage::GetClassID
  79.  *
  80.  * Purpose:
  81.  *  Returns the CLSID of the object represented by this interface.
  82.  *
  83.  * Parameters:
  84.  *  pClsID          LPCLSID in which to store our CLSID.
  85.  *
  86.  * Return Value:
  87.  *  HRESULT         NOERROR on success, error code otherwise.
  88.  */
  89.  
  90. STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
  91.     {
  92.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  93.  
  94.     *pClsID=pObj->m_clsID;
  95.     return NOERROR;
  96.     }
  97.  
  98.  
  99.  
  100.  
  101.  
  102. /*
  103.  * CImpIPersistStorage::IsDirty
  104.  *
  105.  * Purpose:
  106.  *  Tells the caller if we have made changes to this object since
  107.  *  it was loaded or initialized new.
  108.  *
  109.  * Parameters:
  110.  *  None
  111.  *
  112.  * Return Value:
  113.  *  HRESULT         Contains S_OK if we ARE dirty, S_FALSE if NOT dirty,
  114.  *                  that is, "Yes I AM dirty, or NO, I'm clean."
  115.  */
  116.  
  117. STDMETHODIMP CImpIPersistStorage::IsDirty(void)
  118.     {
  119.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  120.  
  121.     return ResultFromScode(pObj->m_fDirty ? S_OK : S_FALSE);
  122.     }
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130. /*
  131.  * CImpIPersistStorage::InitNew
  132.  *
  133.  * Purpose:
  134.  *  Provides the object with the IStorage they can hold on to while
  135.  *  they are running.  Here we can initialize the structure of the
  136.  *  storage and AddRef it for incremental access.  This function will
  137.  *  only be called once in the object's lifetime in lieu of ::Load.
  138.  *
  139.  * Parameters:
  140.  *  pIStorage       LPSTORAGE for the object.
  141.  *
  142.  * Return Value:
  143.  *  HRESULT         NOERROR on success, error code otherwise.
  144.  */
  145.  
  146. STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
  147.     {
  148.     //Nothing to do.  We don't need a storage outside ::Load and ::Save.
  149.     return NOERROR;
  150.     }
  151.  
  152.  
  153.  
  154.  
  155.  
  156. /*
  157.  * CImpIPersistStorage::Load
  158.  *
  159.  * Purpose:
  160.  *  Instructs the object to load itself from a previously saved IStorage
  161.  *  that was handled by ::Save in another object lifetime.  This function
  162.  *  will only be called once in the object's lifetime in lieu of ::InitNew.
  163.  *  The object may hold on to pIStorage here for incremental access.
  164.  *
  165.  * Parameters:
  166.  *  pIStorage       LPSTORAGE from which to load.
  167.  *
  168.  * Return Value:
  169.  *  HRESULT         NOERROR on success, error code otherwise.
  170.  */
  171.  
  172. STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
  173.     {
  174.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  175.     POLYLINEDATA    pl;
  176.     ULONG           cb;
  177.     LPSTREAM        pIStream;
  178.     HRESULT         hr;
  179.  
  180.     if (NULL==pIStorage)
  181.         return ResultFromScode(STG_E_INVALIDPOINTER);
  182.  
  183.     //We don't check ClassStg to remain compatible with other chatpers.
  184.  
  185.     //Open the CONTENTS stream
  186.     hr=pIStorage->OpenStream("CONTENTS", 0, STGM_DIRECT | STGM_READ
  187.         | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  188.  
  189.     if (FAILED(hr))
  190.         return ResultFromScode(STG_E_READFAULT);
  191.  
  192.     //Read all the data into the POLYLINEDATA structure.
  193.     hr=pIStream->Read((LPVOID)&pl, CBPOLYLINEDATA, &cb);
  194.     pIStream->Release();
  195.  
  196.     if (CBPOLYLINEDATA!=cb)
  197.         return ResultFromScode(STG_E_READFAULT);
  198.  
  199.     //CHAPTER6MOD
  200.     //DataSet now internal on CPolyline
  201.     pObj->DataSet(&pl, TRUE, TRUE);
  202.     //End CHAPTER6MOD
  203.     return NOERROR;
  204.     }
  205.  
  206.  
  207.  
  208.  
  209.  
  210. /*
  211.  * CImpIPersistStorage::Save
  212.  *
  213.  * Purpose:
  214.  *  Saves the data for this object to an IStorage which may
  215.  *  or may not be the same as the one previously passed to
  216.  *  ::Load, indicated with fSameAsLoad.
  217.  *
  218.  * Parameters:
  219.  *  pIStorage       LPSTORAGE in which to save our data.
  220.  *  fSameAsLoad     BOOL indicating if this is the same pIStorage
  221.  *                  that was passed to ::Load.  If it was, then
  222.  *                  objects that built up a structure in that storage
  223.  *                  do not have to regenerate the entire thing.
  224.  *
  225.  * Return Value:
  226.  *  HRESULT         NOERROR on success, error code otherwise.
  227.  */
  228.  
  229. STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage, BOOL fSameAsLoad)
  230.     {
  231.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  232.     POLYLINEDATA    pl;
  233.     ULONG           cb;
  234.     LPSTREAM        pIStream;
  235.     HRESULT         hr;
  236.  
  237.     if (NULL==pIStorage)
  238.         return ResultFromScode(STG_E_INVALIDPOINTER);
  239.  
  240.     /*
  241.      * fSameAsLoad is not important to us since we always rewrite
  242.      * an entire stream as well as the identification tags for this
  243.      * object.  Note that we don't bother to check the ClassStg
  244.      * above in ::Load to remain compatible with other revisions
  245.      * of Polyline in other chapters.
  246.      */
  247.  
  248.     WriteClassStg(pIStorage, pObj->m_clsID);
  249.     WriteFmtUserTypeStg(pIStorage, pObj->m_cf, (*pObj->m_pST)[IDS_USERTYPE]);
  250.  
  251.     hr=pIStorage->CreateStream("CONTENTS", STGM_DIRECT | STGM_CREATE
  252.         | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream);
  253.  
  254.     if (FAILED(hr))
  255.         return ResultFromScode(STG_E_WRITEFAULT);
  256.  
  257.     //CHAPTER6MOD
  258.     //DataGet now internal on CPolyline
  259.     pObj->DataGet(&pl);
  260.     //End CHAPTER6MOD
  261.  
  262.     hr=pIStream->Write((LPVOID)&pl, CBPOLYLINEDATA, &cb);
  263.     pIStream->Release();
  264.  
  265.     return (SUCCEEDED(hr) && CBPOLYLINEDATA==cb) ?
  266.         NOERROR : ResultFromScode(STG_E_WRITEFAULT);
  267.     }
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276. /*
  277.  * CImpIPersistStorage::SaveCompleted
  278.  *
  279.  * Purpose:
  280.  *  Notifies the object that the storage in pIStorage has been completely
  281.  *  saved now.  This is called when the user of this object wants to
  282.  *  save us in a completely new storage, and if we normally hang on to
  283.  *  the storage we have to reinitialize ourselves here for this new one
  284.  *  that is now complete.
  285.  *
  286.  * Parameters:
  287.  *  pIStorage       LPSTORAGE of the new storage in which we now live.
  288.  *
  289.  * Return Value:
  290.  *  HRESULT         NOERROR on success, error code otherwise.
  291.  */
  292.  
  293. STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
  294.     {
  295.     /*
  296.      * We have nothing to do here since we do everything in ::Load and
  297.      * ::Save.  For most objects than handle saves this way, they need
  298.      * no code here.  Other objects must release their current storage
  299.      * here and begin using the new one in pIStorage.
  300.      */
  301.  
  302.     return NOERROR;
  303.     }
  304.  
  305.  
  306.  
  307.  
  308.  
  309. /*
  310.  * CImpIPersistStorage::HandsOffStorage
  311.  *
  312.  * Purpose:
  313.  *  Instructs the object that another agent is interested in having total
  314.  *  access to the storage we might be hanging on to from ::InitNew or
  315.  *  ::SaveCompleted.  In this case we must release our hold and await
  316.  *  another call to ::SaveCompleted before we have a hold again.
  317.  *
  318.  *  Situations where this might happen arise in compound document scenarios
  319.  *  where this object might be in-place active but the application wants
  320.  *  to rename and